﻿Object.prototype.clone = function () {
    var copy = this.constructor();
    for (var attr in this) {
        if (this.hasOwnProperty(attr)) copy[attr] = this[attr];
    }
    return copy;
};
Object.prototype.equalsByKey = function (obj, key) {
    var result = false;
    if (key && typeof key == 'string' && obj == null && obj == undefined && typeof this == typeof obj) {
        result = this[key] != undefined && this[key] != null && this[key] == obj[key];
    }
    return result;
};
Object.prototype.equals = function (x) {
    var p;
    for (p in this) {
        if (typeof (x[p]) == 'undefined') { return false; }
    }

    for (p in this) {
        if (this[p]) {
            switch (typeof (this[p])) {
                case 'object':
                    if (!this[p].equals(x[p])) { return false; } break;
                case 'function':
                    if (typeof (x[p]) == 'undefined' ||
                      (p != 'equals' && this[p].toString() != x[p].toString()))
                        return false;
                    break;
                default:
                    if (this[p] != x[p]) { return false; }
            }
        } else {
            if (x[p])
                return false;
        }
    }

    for (p in x) {
        if (typeof (this[p]) == 'undefined') { return false; }
    }

    return true;
}
///**********************************
/// String prototypes
///**********************************
String.prototype.trim = function () {
    return (this == null || this == undefined) ?
		"" :
		this.toString().replace(/^\s+/, "").replace(/\s+$/, "");
};

String.prototype.equals = function (text, ignoreCase, trim) {
    if (text != undefined && text != null) {
        text = text.toString();
        var thisValue = this.toString();
        if (trim) {
            text = text.trim();
            thisValue = thisValue.trim();
        }
        if (ignoreCase) {
            text = text.toLowerCase();
            thisValue = thisValue.toLowerCase();
        }
        return thisValue == text;
    }
    return false;
};
///**********************************
/// Array prototypes
///**********************************
Array.prototype.remove = function (item) {
    var index = this.indexOf(item);
    if (index >= 0) {
        this.splice(index, 1);
        return true;
    }
    return false;
};
Array.prototype.removeAt = function (index) {
    if (index != undefined && index >= 0) {
        this.splice(index, 1);
        return true;
    }
    return false;
};
Array.prototype.clone = function () {
    return this.concat();
};
Array.prototype.find = function (criteriaObject, onlyFirst) {
    var array = new Array();
    if (criteriaObject && typeof criteriaObject != 'undefined') {
        for (var i = 0; i < this.length; i++) {
            var currentObj = this[i];


            if (typeof criteriaObject == 'object') {
                var failed = false;
                for (var key in criteriaObject) {
                    if (currentObj[key] == undefined || currentObj[key] != criteriaObject[key]) {
                        failed = true;
                        break;
                    }
                }

                if (!failed) {
                    if (onlyFirst) {
                        return currentObj.clone();
                    } else {
                        array.push(currentObj.clone());
                    }
                }
            } else {
                if (currentObj == criteriaObject) {
                    if (onlyFirst) {
                        return currentObj;
                    } else {
                        array.push(currentObj);
                    }
                }
            }
        }
    }

    return onlyFirst ? undefined : array;
};
Array.prototype.containsByKey = function (key, value) {
    if (key && typeof key == 'string' && (value || value == 0)) {
        for (var i = 0; i < this.length; i++) {
            var currentObj = this[i];
            if (currentObj[key] == value) {
                return true;
            }
        }
    }
    return false;
};
Array.prototype.contains = function (criteriaObject) {
    if (typeof criteriaObject != 'undefined') {
        return this.find(criteriaObject, true) != undefined;
    }
    return false;
};
Array.prototype.distinct = function () {
    var thisArray = this;
    var uniqueNewArray = [];
    for (var i = 0; i < thisArray.length; i++) {
        var item = thisArray[i];
        if (!uniqueNewArray.contains(item)) {
            uniqueNewArray.push(item);
        }
    }
    return uniqueNewArray;
};
///**********************************
/// Date prototypes
///**********************************
Date.prototype.clone = function () {
    return new Date(this.getTime());
};
Date.prototype.addMilliseconds = function (milliseconds) {
    if (milliseconds) {
        this.setTime(this.getTime() + parseInt(milliseconds));
    }
    return this;
};
Date.prototype.addSeconds = function (seconds) {
    return this.addMilliseconds(seconds * 1000);
};
Date.prototype.addMinutes = function (minutes) {
    return this.addSeconds(minutes * 60);
};
Date.prototype.addHours = function (hours) {
    return this.addMinutes(hours * 60);
};
Date.prototype.addDays = function (days) {
    return this.addHours(days * 24);
};
Date.prototype.addMonths = function (months) {
    if (months) {
        return this.setMonth(this.getMonth() + parseInt(months));
    }
    return this;
};
Date.prototype.addYears = function (years) {
    return this.addMonths(12 * years);
};
Date.prototype.getFirstDayOfMonth = function () {
    var newDate = this.clone();
    newDate.setFullYear(newDate.getFullYear(), newDate.getMonth(), 0);
    newDate.addDays(1);
    return newDate;
};
Date.prototype.getLastDayOfMonth = function () {
    var newDate = this.getFirstDayOfMonth();
    newDate.addMonths(1);
    newDate.addDays(-1);
    return newDate;
};
Date.prototype.compare = function (date, absolute) {
    var result = 0;
    if (date && typeof date == 'object') {
        result = this.getTime() - date.getTime();
        if (absolute && result < 0) {
            result = result * -1;
        }
    }
    return result;
};
Date.prototype.format = function (mask) {
    var d = this;
    var zeroize = function (value, length) {
        if (!length) length = 2;
        value = String(value);
        for (var i = 0, zeros = ''; i < (length - value.length); i++) {
            zeros += '0';
        }
        return zeros + value;
    };

    return mask.replace(/"[^"]*"|'[^']*'|\b(?:d{1,4}|M{1,4}|m{1,2}|yy(?:yy)?|([hHMstT])\1?|[lLZ])\b/g, function ($0) {
        switch ($0) {
            case 'd': return d.getDate();
            case 'dd': return zeroize(d.getDate());
            case 'ddd': return ['Sun', 'Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat'][d.getDay()];
            case 'dddd': return ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][d.getDay()];
            case 'M': return d.getMonth() + 1;
            case 'MM': return zeroize(d.getMonth() + 1);
            case 'MMM': return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][d.getMonth()];
            case 'MMMM': return ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'][d.getMonth()];
            case 'yy': return String(d.getFullYear()).substr(2);
            case 'yyyy': return d.getFullYear();
            case 'h': return d.getHours() % 12 || 12;
            case 'hh': return zeroize(d.getHours() % 12 || 12);
            case 'H': return d.getHours();
            case 'HH': return zeroize(d.getHours());
            case 'm': return d.getMinutes();
            case 'mm': return zeroize(d.getMinutes());
            case 's': return d.getSeconds();
            case 'ss': return zeroize(d.getSeconds());
            case 'fff':
                return zeroize(d.getMilliseconds(), 3);
            case 'ff':
                var m = d.getMilliseconds();
                if (m > 99) m = Math.round(m / 10);
                return zeroize(m);
            case 'tt': return d.getHours() < 12 ? 'am' : 'pm';
            case 'TT': return d.getHours() < 12 ? 'AM' : 'PM';
            case 'Z': return d.toUTCString().match(/[A-Z]+$/);
                // Return quoted strings with the surrounding quotes removed
            default: return $0.substr(1, $0.length - 2);
        }
    });
};
